﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using EasyDDD.Infrastructure.EFCore.Repository;
using EasyDDD.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Configuration;
using FluentValidation.AspNetCore;
using EasyDDD.TemplateModule.Repository;
using EasyDDD.TemplateModule.Records;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;

namespace EasyDDD.TemplateModule.Application
{
    public static class ServiceCollectionExtensions
    {
        public static IServiceCollection AddTemplateModule(this IServiceCollection services, IConfiguration configuration)
        {
            var moduleName = "TemplateModule";

            Console.WriteLine("moduleName {0}", moduleName);
            Console.WriteLine("Assembly.GetCallingAssembly().FullName:{0}", Assembly.GetCallingAssembly().FullName);
            Console.WriteLine("Assembly.GetEntryAssembly().FullName:{0}", Assembly.GetEntryAssembly()?.FullName);
            Console.WriteLine("Assembly.GetExecutingAssembly().FullName:{0}", Assembly.GetExecutingAssembly().FullName);

            if (moduleName != null && configuration.GetSection(moduleName).Exists())
            {
                configuration = configuration.GetSection(moduleName);
            }


            services.AddAutoMapper(typeof(AutoMapperProfile));
            services.AddFluentValidationAutoValidation();
            services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly());

            services.AddRepository<TemplateModuleRepositoryDbContext>()
                .AddDbContext<TemplateModuleRepositoryDbContext>(o => o.UseNpgsql(configuration.GetConnectionString("PostgreSQL")));
            services.AddRecords<TemplateModuleRecordsDbContext>()
                .AddDbContext<TemplateModuleRecordsDbContext>(o => o.UseNpgsql(configuration.GetConnectionString("PostgreSQL")));

            services.AddMediatR(cfg =>
            {
                cfg.RegisterServicesFromAssemblies(Assembly.GetExecutingAssembly());
                cfg.AddOpenBehavior(typeof(CommandUnitOfWorkBehavior<,>));
            });
            services.AddCap(o =>
            {
                o.UseEntityFramework<TemplateModuleRepositoryDbContext>();
                //o.UseRabbitMQ(cfg => configuration.GetSection("RabbitMQ").Bind(cfg));
                o.UseRedis(cfg => configuration.GetSection("ConnectionStrings:Redis").Bind(cfg));
                o.UseDashboard();
            });

            services.AddScoped<IUnitOfWork>(p => p.GetRequiredService<TemplateModuleRepositoryDbContext>());
            services.AddIntegrationEventHandler();

            services.AddDomainSevice<Domain.DomainAssemblyLoadMark>();

           
            services.AddAuthorization();
            services.AddAuthentication(x =>
            {
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            }).AddJwtBearer(options =>
            {
                options.RequireHttpsMetadata = false;
                options.SaveToken = true;
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(configuration.GetValue<string>("JWT:Secret")!)),//JWT秘钥
                    //ValidIssuer = configuration.GetValue<string>("JWT:ISyouuser"),//发行者,
                    //ValidAudience = configuration.GetValue<string>("JWT:IsAudience"),//接收者,
                    ValidateIssuer = false,
                    ValidateAudience = false,
                    // 是否验证Token有效期，使用当前时间与Token的Claims中的NotBefore和Expires对比
                    ValidateLifetime = true,
                    //注意这是缓冲过期时间，总的有效时间等于这个时间加上jwt的过期时间，如果不配置，默认是5分钟
                    ClockSkew = TimeSpan.Zero
                };
            });

            return services;
        }
    }
}

